package com.xyq.friend.service.exam;


import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xyq.common.core.constants.Constants;
import com.xyq.common.core.domain.TableDataInfo;
import com.xyq.common.core.utils.ThreadLocalUtil;
import com.xyq.friend.domain.exam.dto.ExamQueryDTO;
import com.xyq.friend.domain.exam.dto.ExamRankDTO;
import com.xyq.friend.domain.exam.vo.ExamRankVO;
import com.xyq.friend.domain.exam.vo.ExamVO;
import com.xyq.friend.manager.ExamCacheManager;
import com.xyq.friend.mapper.ExamMapper;
import com.xyq.friend.mapper.UserExamMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Service
public class ExamServiceImpl implements ExamService{

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamCacheManager examCacheManager ;

    @Autowired
    private UserExamMapper userExamMapper ;

    @Override
    public List<ExamVO> list(ExamQueryDTO examQueryDTO) {
        // 加入这条语句就足够可以实现 分页查询功能
        PageHelper.startPage(examQueryDTO.getPageNum() , examQueryDTO.getPageSize());
        return  examMapper.selectExamList(examQueryDTO) ;
    }

    @Override
    public TableDataInfo redisList(ExamQueryDTO examQueryDTO) {
        //  从redis里获取数据
        // 1. 先判断redis里有没有数据 , 如果没有数据要去 MySQL里查
          Long listSize = examCacheManager.getListSize(examQueryDTO.getType(),null);
          List<ExamVO> examVOList ;
          // 如果 redis里没有这个列表的数据
        if(listSize == null || listSize <= 0){
              // 1. 为空就从数据库里查询
            examVOList = list(examQueryDTO);  // 调用上面 查找mysql数据库的方法查询
            // 2. 同时 刷新 redis里的缓存数据
            examCacheManager.refreshCache(examQueryDTO.getType(), null);
            listSize = new PageInfo<>(examVOList).getTotal();
        }else{
            // 如果redis里的数据不为空 ,就去redis里获取竞赛列表数据
            examVOList = examCacheManager.getExamVOList(examQueryDTO , null);
            listSize = examCacheManager.getListSize(examQueryDTO.getType() , null);
        }
        // 返回 查询到的竞赛列表, 同时加上 total 列表总数
        // 不能使用 TableDataInfo的方法来获取total , 但是上面的 listSize 就是获取到的列表总数
        // 获取 总数 ,
        // 判断list是否为null
        if(CollectionUtil.isEmpty(examVOList)){
           return TableDataInfo.empty();    // 如果list是空返回empty（） ；
        }
        // 如果不是为空 返回 list 和 总的 数量
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<ExamVO> sum ;
        // 查询日期
        if(!(examQueryDTO.getStartTime().isEmpty() && examQueryDTO.getEndTime().isEmpty())){
            sum = new ArrayList<>() ;
           for(ExamVO examVO : examVOList){
               if(!(examVO.getStartTime().isBefore(LocalDateTime.parse(examQueryDTO.getStartTime(),df)) ||
                 examVO.getEndTime().isAfter(LocalDateTime.parse(examQueryDTO.getEndTime(),df)))){
                   sum.add(examVO);
               }
           }
           // 添加是否报名enter值
            assembleExamVOList(sum);
           return TableDataInfo.success(sum ,listSize );
        }
        // 处理 用户是否已报名某个竞赛
        assembleExamVOList(examVOList);
        return TableDataInfo.success(examVOList ,listSize );
    }

    // 获取当前竞赛里的第一题
    @Override
    public String getFirstQuestion(Long examId) {
       // 1. 先去  缓存里 判断缓存里是否有数据
        // 判断列表是否为空
        Long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize == null || listSize <= 0){
            // 为空 , 刷新缓存
            examCacheManager.refreshExamQuestionListCaChe(examId) ;
        }
        // 获取第一题题目
        Long firstQuestion = examCacheManager.getFirstQuestion(examId);
        return firstQuestion.toString();
    }
    // 获取竞赛题目 上一题
    @Override
    public String preExamQuestion(Long examId, Long questionId) {
        // 判断列表是否为空
        Long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize == null || listSize <= 0){
            // 为空 , 刷新缓存
            examCacheManager.refreshExamQuestionListCaChe(examId); ;
        }
        // 获取当前 题目的上一题
        return examCacheManager.preQuestion( examId, questionId).toString();
    }

    // 获取竞赛题目下一题
    @Override
    public String nextExamQuestion(Long examId, Long questionId) {
        // 判断列表是否为空
        Long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize == null || listSize <= 0){
            // 为空 , 刷新缓存
            examCacheManager.refreshExamQuestionListCaChe(examId); ;
        }
        // 获取当前 题目的上一题
        return examCacheManager.nextQuestion(examId , questionId).toString();
    }
   // 获取竞赛排名

    @Override
    public TableDataInfo rankList(ExamRankDTO examRankDTO) {
        //  从redis里获取数据
        // 1. 先判断redis里有没有数据 , 如果没有数据要去 MySQL里查
        Long listSize = examCacheManager.getRankListSize(examRankDTO.getExamId());
        List<ExamRankVO> examRankVOList ;
        // 如果 redis里没有这个列表的数据
        if(listSize == null || listSize <= 0){
            // 1. 为空就从数据库里查询
            examRankVOList = userExamMapper.selectExamRankVOList(examRankDTO.getExamId());  // 调用上面 查找mysql数据库的方法查询
            // 2. 同时 刷新 redis里的缓存数据
            examCacheManager.refreshCache(examRankVOList , examRankDTO.getExamId() );
            listSize = new PageInfo<>(examRankVOList).getTotal();
        }else{
            // 如果redis里的数据不为空 ,就去redis里获取竞赛列表数据
            examRankVOList = examCacheManager.getExamRankVOList(examRankDTO);
            listSize =examCacheManager.getRankListSize(examRankDTO.getExamId());
        }
        // 返回 查询到的竞赛列表, 同时加上 total 列表总数
        // 不能使用 TableDataInfo的方法来获取total , 但是上面的 listSize 就是获取到的列表总数
        // 获取 总数 ,
        // 判断list是否为null
        if(CollectionUtil.isEmpty(examRankVOList)){
            return TableDataInfo.empty();    // 如果list是空返回empty（） ；
        }
        // 如果不是为空 返回 list 和 总的 数量

        return TableDataInfo.success(examRankVOList ,listSize );
    }

    // 判断段当前用户是否已经报名这个竞赛
    private void assembleExamVOList(List<ExamVO> examVOList){
        // 获取当前用户的id
       Long userId =  ThreadLocalUtil.get(Constants.USER_ID , Long.class) ;
       if(userId == null) return;
       // 在redis里获取 用户报名的竞赛列表缓存 , 所有的已报名的竞赛id
        List<Long> userExamList = examCacheManager.getAllUserExamList(userId) ;
        // 如果这个竞赛,在用户报名的竞赛列表里 , ,就把 enter 置为 true
        if(CollectionUtil.isEmpty(userExamList)){
            return;
        }
        for(ExamVO examVO : examVOList){
            if(userExamList.contains(examVO.getExamId())){
                examVO.setEnter(true);
            }
        }
    }

}
